<template>
	<view v-if="visibleSync" :style="[customStyle, {
		zIndex: zIndex - 2
	}]" class="sol-drawer" hover-stop-propagation>
		<sol-mask :duration="duration" :custom-style="maskCustomStyle" :click-able="maskCloseable" :z-index="zIndex - 4"
			:show="showDrawer && mask" @click="$_click('mask')"></sol-mask>
		<view class="sol-drawer_content" @touchmove.stop.prevent @tap.stop.prevent :style="[style]">
			<slot name="default" v-if="customSlot"></slot>
			<template v-else>
				<text class="sol-drawer_title line-1" v-if="title" v-text="title">标题</text>
				<scroll-view class="sol-drawer__scroll-view" scroll-y="true">
					<slot name="default"></slot>
				</scroll-view>
				<view class="sol-drawer_btns">
					<button class="sol-drawer_btn sol-drawer_btn-error" @click="$_click('error')" v-if="errorText"
						v-text="errorText">严重</button>
					<button class="sol-drawer_btn sol-drawer_btn-primary" @click="$_click('primary')" v-if="primaryText"
						v-text="primaryText">高亮</button>
					<button class="sol-drawer_btn sol-drawer_btn-confirm" @click="$_click('confirm')" v-if="confirmText"
						v-text="confirmText">灰色</button>
					<button class="sol-drawer_btn sol-drawer_btn-cancel" @click="$_click('cancel')" v-if="cancelText"
						v-text="cancelText">无色</button>
				</view>
			</template>
		</view>
	</view>
</template>

<script>
	/**
	 * drawer 抽屉 根据uview popup改
	 * @description 弹出层容器
	 * @tutorial https://www.uviewui.com/components/popup.html
	 * @property {String} value 显示true
	 * @property {Boolean} mask 是否显示遮罩（默认true）
	 * @property {Boolean} mask-close-able 点击遮罩是否可以关闭弹出层（默认true）
	 * @property {Boolean} mask-custom-style 遮罩样式 
	 * @property {Object} custom-style 用户自定义样式
	 * @property {Numberr | String} border-radius 弹窗圆角值（默认0）
	 * @property {Numberr | String} z-index 弹出内容的z-index值（默认1075） 
	 * @property {Numberr | String} width 宽 
	 * @property {Numberr | String} height 高 
	 * @property {Numberr | String} duration 弹出时间 
	 * @property {String} title 标题
	 * @property {String} custom-slot 自定义插槽
	 * @property {String} error-text 错误按钮文字
	 * @property {String} primary-text 高亮按钮文字
	 * @property {String} confirm-text 确认按钮文字
	 * @property {String} cancel-text 取消按钮文字 
	 * @event {Function} click 按钮点击
	 * @example <sol-popup v-model="show" @click><view>出淤泥而不染，濯清涟而不妖</view></sol-popup>
	 */

	export default {
		name: 'sol-popup',

		props: {
			// 显示状态
			value: {
				type: Boolean,
				default: false
			},
			// 是否显示遮罩
			mask: {
				type: Boolean,
				default: true
			},
			// 是否可以通过点击遮罩进行关闭
			maskCloseable: {
				type: Boolean,
				default: true
			},
			// 遮罩的样式，一般用于修改遮罩的透明度
			maskCustomStyle: {
				type: Object,
				default () {
					return {}
				}
			},
			// 用户自定义样式
			customStyle: {
				type: Object,
				default () {
					return {};
				}
			},
			// 显示显示弹窗的圆角，单位rpx
			borderRadius: {
				type: [Number, String],
				default: 32
			},
			// 层级
			zIndex: {
				type: [Number, String],
				default: 320
			},
			// 宽度，只对左，右，中部弹出时起作用，单位rpx，或者"auto"
			// 或者百分比"50%"，表示由内容撑开高度或者宽度，优先级高于length参数
			width: {
				type: String,
				default: ''
			},
			// 高度，只对上，下，中部弹出时起作用，单位rpx，或者"auto"
			// 或者百分比"50%"，表示由内容撑开高度或者宽度，优先级高于length参数
			height: {
				type: String,
				default: ''
			},
			// 遮罩打开或收起的动画过渡时间，单位ms
			duration: {
				type: [String, Number],
				default: 300
			},
			// 标题
			title: {
				type: String,
				default: ''
			},
			// 自定义插槽
			customSlot: {
				type: Boolean,
				default: false
			},
			// 严重错误按钮
			errorText: {
				type: String,
				default: ''
			},
			// 高亮按钮
			primaryText: {
				type: String,
				default: ''
			},
			// 灰色按钮
			confirmText: {
				type: String,
				default: ''
			},
			// 无色按钮
			cancelText: {
				type: String,
				default: ''
			},
		},

		data() {
			return {
				visibleSync: false,
				showDrawer: false,
				closeFromInner: false, // value的值改变，是发生在内部还是外部
			};
		},

		computed: {
			style() {
				let style = {
					width: this.width ? this.getUnitValue(this.width) : 'auto',
					height: this.height ? this.getUnitValue(this.height) : 'auto',
				};
				style.zIndex = this.zIndex;
				// 如果用户设置了borderRadius值，添加弹窗的圆角
				if (this.borderRadius) {
					style.borderRadius = `${this.borderRadius}rpx`;
					// 不加可能圆角无效
					style.overflow = 'hidden';
				}
				if (this.duration) {
					style.transition = `all ${this.duration / 1000}s linear`;
					style.animation = `slide-up ${this.duration / 1000}s 1`;
				}
				return style;
			},
		},

		watch: {
			value(val) {
				if (val) {
					this.open();
				} else if (!this.closeFromInner) {
					this.close();
				}
				this.closeFromInner = false;
			}
		},

		mounted() {
			// 组件渲染完成时，检查value是否为true，如果是，弹出popup
			this.value && this.open();
		},

		methods: {
			// 判断传入的值，是否带有单位，如果没有，就默认用rpx单位
			getUnitValue(val) {
				if (/(%|px|rpx|auto)$/.test(val)) return val;
				else return val + 'rpx'
			},
			close() {
				// 标记关闭是内部发生的，否则修改了value值，导致watch中对value检测，导致再执行一遍close
				// 造成@close事件触发两次
				this.closeFromInner = true;
				this.change('showDrawer', 'visibleSync', false);
			},
			open() {
				this.change('visibleSync', 'showDrawer', true);
			},
			// 此处的原理是，关闭时先通过动画隐藏弹窗和遮罩，再移除整个组件
			change(param1, param2, status) {
				this[param1] = status;
				if (status) {
					this.$nextTick(() => {
						this[param2] = status;
						this.$emit(status ? 'open' : 'close');
					});
				} else {
					this.$nextTick(() => {
						this[param2] = status;
						this.$emit(status ? 'open' : 'close');
					});
				}
			},
			// 按钮点击类型
			$_click(type) {
				this.$emit('click', type);
			},
		}
	};
</script>

<style scoped lang="scss">
	.sol-drawer {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		overflow: hidden;

		&_content {
			position: fixed;
			bottom: 0;
			left: 0;
			right: 0;
			width: auto;
			height: auto;
			z-index: 1003;
			transition: all 0.25s linear;
			margin: 42rpx 28rpx;
			padding: 56rpx 32rpx;
			background-color: #474e54;
		}

		&_title {
			letter-spacing: 5rpx;
			font-size: 42rpx;
			font-weight: bold;
			color: #DDDDDD;
			width: 80%;
			text-align: center;
			display: block;
			margin: 0 auto;
		}

		&_btns {
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;
		}

		&_btn {
			width: 80%;
			height: 96rpx;
			border-radius: 50rpx;
			line-height: 96rpx;
			font-size: 32rpx;
			font-weight: 400;
			letter-spacing: 6rpx;

			&-error {
				border: 2rpx #9b6e6b solid;
				background-color: #9b6e6b;
				color: #DDDDDD;
				margin-bottom: 28rpx;
			}
			
			&-primary {
				border: 2rpx #607d8b solid;
				background-color: #607d8b;
				color: #DDDDDD;
				margin-bottom: 28rpx;
			}

			&-confirm {
				border: 2rpx #576069 solid;
				background-color: #576069;
				color: #DDDDDD;
				margin-bottom: 28rpx;
			}

			&-cancel {
				border: 2rpx #474e54 solid;
				background-color: #474e54;
				color: #DDDDDD;
			}
		}

		&__scroll-view {
			width: 100%;
			height: 100%;
			padding: 42rpx 0;
		}
	}
</style>
